import json
import re

from django import http
from django.contrib.auth import login, authenticate, logout
from django.contrib.auth.mixins import LoginRequiredMixin
from django.core.paginator import Paginator, EmptyPage
from django.http import QueryDict, JsonResponse
from django.shortcuts import render, redirect
from django.urls import reverse
from django.views import View
from pymysql import DatabaseError

from apps.areas.models import Address
from apps.orders.models import OrderInfo
from apps.users.models import User
from utils import constants
from utils.response_code import RETCODE


class RegisterView(View):
    """用户注册"""

    def get(self, request):
        """
        提供注册界面
        :param request: 请求对象
        :return: 注册界面
        """
        return render(request, 'register.html')

    def post(self, request):
        '''注册逻辑'''
        # 获取参数
        username = request.POST.get('username')
        password = request.POST.get('password')
        password2 = request.POST.get('password2')
        mobile = request.POST.get('mobile')

        # 校验参数
        # 判断参数是否齐全
        if not all([username, password, password2, mobile]):
            return http.HttpResponseBadRequest('缺少必传参数')
        # 判断用户名是否是5-20个字符
        if not re.match(r'^[a-zA-Z0-9_]{5,20}$', username):
            return http.HttpResponseBadRequest('请输入5-20个字符的用户名')
        # 判断密码是否是8-20个数字
        if not re.match(r'^[0-9A-Za-z]{8,20}$', password):
            return http.HttpResponseBadRequest('请输入8-20位的密码')
        # 判断两次密码是否一致
        if password != password2:
            return http.HttpResponseBadRequest('两次输入的密码不一致')
        # 判断手机号是否合法
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return http.HttpResponseBadRequest('请输入正确的手机号码')

        # 保存注册数据
        try:
            user=User.objects.create_user(username=username, password=password, mobile=mobile)
        except DatabaseError:
            return render(request, 'register.html', {'register_errmsg': '注册失败'})

        # 响应注册结果
        response = redirect(reverse('users:login'))

        # 注册时用户名写入到cookie，有效期15天
        response.set_cookie('username', user.username, max_age=3600 * 24 * 15)

        return response
        # return redirect(reverse('users:login'))


class LoginView(View):
    '''用户登录'''

    def get(self, request):
        '''登录'''

        return render(request, 'login.html')

    def post(self, request):
        """
        实现登录逻辑
        :param request: 请求对象
        :return: 登录结果
        """
        # 接收参数
        username = request.POST.get('username')
        password = request.POST.get('password')
        # remembered = request.POST.get('remembered')
        print(username, password)
        # 校验参数
        # 判断参数是否齐全
        if not all([username, password]):
            return http.HttpResponseBadRequest('缺少必传参数')

        # 判断用户名是否是5-20个字符
        if not re.match(r'^[a-zA-Z0-9_-]{5,20}$', username):
            # return http.HttpResponseBadRequest('请输入正确的用户名或手机号')
            return render(request, 'login.html', {'account_errmsg': '请输入正确的用户名或手机号'})
        # print(1111)
        # 判断密码是否是8-20个数字
        if not re.match(r'^[0-9A-Za-z]{8,20}$', password):
            # return http.HttpResponseBadRequest('密码最少8位，最长20位')
            return render(request, 'login.html', {'account_errmsg': '密码最少8位，最长20位'})
        # print(22222)
        # 认证登录用户
        user = authenticate(username=username, password=password)
        if user is None:
            return render(request, 'login.html', {'account_errmsg': '用户名或密码错误'})

        try:
            User.objects.filter(username=username, password=password)
        except Exception as e:
            return render(request, 'login.html', {'errmsg': '用户名或密码错误'})
        # print(333333)
        # 实现状态保持
        login(request, user)
        # 设置状态保持的周期
        # if remembered != 'on':
        #     # 没有记住用户：浏览器会话结束就过期
        #     request.session.set_expiry(0)
        # else:
        #     # 记住用户：None表示两周后过期
        #     request.session.set_expiry(None)

        # 响应登录结果
        next = request.GET.get('next')
        if next:
            response = redirect(next)
        else:
            response = redirect(reverse('index:index'))

        response.set_cookie('username', user.username, max_age=3600 * 24 * 15)

        return response


class LogoutView(View):
    """退出登录"""

    def get(self, request):
        """实现退出登录逻辑"""
        # 清理session
        logout(request)

        # 退出登录，重定向到登录页
        response = redirect(reverse('index:index'))

        # 退出登录时清除cookie中的username
        response.delete_cookie('username')

        return response


class UserView(LoginRequiredMixin, View):
    '''用户中心'''

    def get(self, request):

        return render(request, 'usercenter.html')

    def post(self, request):

        nickname = request.POST.get('nickname')
        username = request.POST.get('username')
        sex = request.POST.get('sex')
        mobile = request.POST.get('mobile')
        email = request.POST.get('email')
        # print(nickname, username, sex, mobile, email)
        if not all([nickname, username, sex, mobile, email]):
            return http.HttpResponseBadRequest('参数不全')

        # 判断用户名是否是5-20个字符
        if not re.match(r'^[a-zA-Z0-9_-]{5,20}$', username):
            return http.HttpResponseBadRequest('用户名')
        # 判断用户名是否是5-20个字符
        if not re.match(r'^[a-zA-Z0-9_-]{5,20}$', nickname):
            return http.HttpResponseBadRequest('昵称')
        # 判断手机号是否合法
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return http.HttpResponseBadRequest('请输入正确的手机号码')
        if not re.match(r'^[a-z0-9][\w\.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}$', email):
            return http.HttpResponseBadRequest('参数email有误')

        # if not  request.user.is_authenticated:
        #     return http.HttpResponseBadRequest('')
        userid = request.user.id
        # 修改数据库
        try:
            User.objects.filter(id=userid).update(username=username, nickname=nickname, sex=sex, email=email,
                                                  mobile=mobile)


        except Exception as e:
            return http.HttpResponseBadRequest('修改数据失败')

        # return render(request, 'usercenter.html')
        return JsonResponse({'code':'OK','errmsg':'修改成功'})


class ChangePasswordView(LoginRequiredMixin, View):
    """修改密码"""

    def get(self, request):
        """展示修改密码界面"""
        return render(request, 'user_Password.html')

    def post(self, request):

        # 获取数据
        old_password = request.POST.get('old_password')
        new_password = request.POST.get('new_password')
        new_password2 = request.POST.get('new_password2')

        if not all([old_password, new_password, new_password2]):
            return http.HttpResponseBadRequest('缺少参数')

        if not re.match(r'^[0-9A-Za-z]{8,20}$', new_password):
            return http.HttpResponseBadRequest('密码最少8位，最长20位')
        if new_password != new_password2:
            return http.HttpResponseBadRequest('两次输入的密码不一致')

            # 3.检验旧密码是否正确
        if not request.user.check_password(old_password):
            return render(request, 'user_Password.html', {'origin_password_errmsg': '原始密码错误'})
            # 4.更新新密码
        try:
            request.user.set_password(new_password)
            request.user.save()
        except Exception as e:
            return render(request, 'user_Password.html', {'change_password_errmsg': '修改密码失败'})
            # 5.退出登陆,删除登陆信息
        logout(request)
        # 6.跳转到登陆页面
        response = redirect(reverse('users:login'))

        response.delete_cookie('username')

        return response


class AddressView(LoginRequiredMixin,View):

    def get(self,request):
        # 获取用户地址列表
        addresses = Address.objects.filter(user=request.user, is_deleted=False)

        address_dict_list = []
        for address in addresses:
            address_dict = {
                "id": address.id,
                "title": address.title,
                "receiver": address.receiver,
                # "province": address.province.name,
                # "province_id": address.province_id,
                # "city": address.city.name,
                # "city_id": address.city_id,
                # "district": address.district.name,
                # "district_id": address.district_id,
                "place": address.place,
                "mobile": address.mobile,
                "tel": address.tel,
                "email": address.email
            }
            address_dict_list.append(address_dict)

        context = {
            # 'default_address_id': request.user.default_address_id,
            'addresses': address_dict_list,
        }
        print(address_dict_list)


        return render(request,'user_address.html',context)

    def post(self, request):
        """实现新增地址逻辑"""
        
        # 判断是否超过地址上限：最多20个
        # Address.objects.filter(user=request.user).count()
        # count = request.user.addresses.count()
        # if count >= constants.USER_ADDRESS_COUNTS_LIMIT:
        #     return http.JsonResponse({'code': RETCODE.THROTTLINGERR, 'errmsg': '超过地址数量上限'})

        # 接收参数
        #     # 获取数据
        receiver = request.POST.get('receiver')
        place = request.POST.get('place')
        email = request.POST.get('email')
        mobile = request.POST.get('mobile')
        tel = request.POST.get('tel')
        print(1111)
        # 校验参数
        if not all([receiver, place, mobile,email]):
            return http.HttpResponseBadRequest('缺少必传参数')
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return http.HttpResponseBadRequest('参数mobile有误')
        if tel:
            if not re.match(r'^(0[0-9]{2,3}-)?([2-9][0-9]{6,7})+(-[0-9]{1,4})?$', tel):
                return http.HttpResponseBadRequest('参数tel有误')
        if email:
            if not re.match(r'^[a-z0-9][\w\.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}$', email):
                return http.HttpResponseBadRequest('参数email有误')
        print(2222)
        # 保存地址信息
        try:
            address = Address.objects.create(
                user=request.user,
                title = receiver,
                receiver = receiver,
                # province_id = province_id,
                # city_id = city_id,
                # district_id = district_id,
                place = place,
                mobile = mobile,
                tel = tel,
                email = email
            )

            # 设置默认地址
            # if not request.user.default_address:
            #     request.user.default_address = address
            #     request.user.save()
        except Exception as e:
            return http.JsonResponse({'code': RETCODE.DBERR, 'errmsg': '新增地址失败'})

        # 新增地址成功，将新增的地址响应给前端实现局部刷新
        address_dict = {
            "id": address.id,
            "title": address.title,
            "receiver": address.receiver,
            # "province": address.province.name,
            # "city": address.city.name,
            # "district": address.district.name,
            "place": address.place,
            "mobile": address.mobile,
            "tel": address.tel,
            "email": address.email
        }
        print(3333333333333)
        # 响应保存结果
        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '新增地址成功', 'address':address_dict})



class UserOrderInfoView(LoginRequiredMixin, View):
    """我的订单"""

    def get(self, request, page_num):
        """提供我的订单页面"""
        user = request.user
        # 查询订单
        orders = user.orderinfo_set.all().order_by("-create_time")
        # 遍历所有订单
        for order in orders:
            # 绑定订单状态
            order.status_name = OrderInfo.ORDER_STATUS_CHOICES[order.status-1][1]
            # 绑定支付方式
            order.pay_method_name = OrderInfo.PAY_METHOD_CHOICES[order.pay_method-1][1]
            order.sku_list = []
            # 查询订单商品
            order_goods = order.skus.all()
            # 遍历订单商品
            for order_good in order_goods:
                sku = order_good.sku
                sku.count = order_good.count
                sku.amount = sku.price * sku.count
                order.sku_list.append(sku)

        # 分页
        page_num = int(page_num)
        try:
            paginator = Paginator(orders, constants.ORDERS_LIST_LIMIT)
            page_orders = paginator.page(page_num)
            total_page = paginator.num_pages
        except EmptyPage:
            return http.HttpResponseNotFound('订单不存在')

        context = {
            "page_orders": page_orders,
            'total_page': total_page,
            'page_num': page_num,
        }
        return render(request, "user_center_order.html", context)
